package com.dd.admin.business.storage.service;

import com.dd.admin.common.config.QiniuProperties;
import com.dd.admin.common.exception.ApiException;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 七牛云存储服务类
 * 提供文件上传、删除、查询和访问token生成功能
 */
@Slf4j
@Service
public class QiniuStorageService {

    @Autowired
    private QiniuProperties qiniuProperties;

    /**
     * 获取七牛云配置
     */
    private Configuration getConfiguration() {
        // 根据配置的区域选择对应的Region
        Region region;
        switch (qiniuProperties.getRegion().toLowerCase()) {
            case "huadong":
                region = Region.huadong();
                break;
            case "huabei":
                region = Region.huabei();
                break;
            case "huanan":
                region = Region.huanan();
                break;
            case "beimei":
                region = Region.beimei();
                break;
            default:
                region = Region.autoRegion();
                break;
        }
        return new Configuration(region);
    }

    /**
     * 获取Auth认证对象
     */
    private Auth getAuth() {
        return Auth.create(qiniuProperties.getAccessKey(), qiniuProperties.getSecretKey());
    }

    /**
     * 上传文件到七牛云
     * @param file 要上传的文件
     * @param fileName 文件名（如果为空则自动生成）
     * @param directory 存储目录
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file, String fileName, String directory) {
        log.info("开始上传文件到七牛云，目录：{}，文件名：{}", directory, fileName);
        
        try {
            // 如果文件名为空，则生成UUID文件名
            if (fileName == null || fileName.trim().isEmpty()) {
                String originalFilename = file.getOriginalFilename();
                String extension = "";
                if (originalFilename != null && originalFilename.contains(".")) {
                    extension = originalFilename.substring(originalFilename.lastIndexOf("."));
                }
                fileName = UUID.randomUUID().toString().replace("-", "") + extension;
            }
            
            // 确保目录以/结尾
            if (directory != null && !directory.isEmpty() && !directory.endsWith("/")) {
                directory = directory + "/";
            }
            
            Configuration cfg = getConfiguration();
            UploadManager uploadManager = new UploadManager(cfg);
            
            byte[] uploadBytes = file.getBytes();
            Auth auth = getAuth();
            String upToken = auth.uploadToken(qiniuProperties.getBucketName());
            
            String key = (directory == null ? "" : directory) + fileName;
            Response response = uploadManager.put(uploadBytes, key, upToken);
            
            if (response.isOK()) {
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
                String fileUrl = qiniuProperties.getDomain() + "/" + putRet.key;
                log.info("文件上传成功，访问URL：{}", fileUrl);
                return fileUrl;
            } else {
                log.error("文件上传失败，响应码：{}，响应信息：{}", response.statusCode, response.bodyString());
                throw new ApiException("文件上传失败：" + response.bodyString());
            }
            
        } catch (Exception ex) {
            log.error("文件上传异常：", ex);
            throw new ApiException("文件上传失败：" + ex.getMessage());
        }
    }

    /**
     * 删除七牛云文件
     * @param directory 文件目录
     * @param fileName 文件名
     * @return 是否删除成功
     */
    public boolean deleteFile(String directory, String fileName) {
        log.info("开始删除七牛云文件，目录：{}，文件名：{}", directory, fileName);
        
        try {
            Configuration cfg = getConfiguration();
            Auth auth = getAuth();
            BucketManager bucketManager = new BucketManager(auth, cfg);
            
            // 确保目录以/结尾
            if (directory != null && !directory.isEmpty() && !directory.endsWith("/")) {
                directory = directory + "/";
            }
            
            String key = (directory == null ? "" : directory) + fileName;
            bucketManager.delete(qiniuProperties.getBucketName(), key);
            
            log.info("文件删除成功，key：{}", key);
            return true;
            
        } catch (QiniuException ex) {
            log.error("文件删除失败，错误码：{}，错误信息：{}", ex.code(), ex.getMessage());
            return false;
        }
    }

    /**
     * 获取文件目录列表
     * @return 目录列表
     */
    public List<String> getDirectoryList() {
        log.info("开始获取七牛云文件目录列表");
        
        List<String> result = new ArrayList<>();
        
        try {
            Configuration cfg = getConfiguration();
            Auth auth = getAuth();
            BucketManager bucketManager = new BucketManager(auth, cfg);
            
            String prefix = "";
            int limit = 1000;
            String delimiter = "";
            
            BucketManager.FileListIterator fileListIterator = 
                bucketManager.createFileListIterator(qiniuProperties.getBucketName(), prefix, limit, delimiter);
            
            while (fileListIterator.hasNext()) {
                FileInfo[] items = fileListIterator.next();
                for (FileInfo item : items) {
                    String key = item.key;
                    // 判断是否为目录（以/结尾）
                    if (key.endsWith("/")) {
                        result.add(key);
                    }
                }
            }
            
            log.info("获取目录列表成功，共{}个目录", result.size());
            return result;
            
        } catch (Exception ex) {
            log.error("获取目录列表失败：", ex);
            throw new ApiException("获取目录列表失败：" + ex.getMessage());
        }
    }

    /**
     * 获取文件列表
     * @param directory 目录前缀
     * @return 文件列表
     */
    public List<FileInfo> getFileList(String directory) {
        log.info("开始获取文件列表，目录：{}", directory);
        
        List<FileInfo> result = new ArrayList<>();
        
        try {
            Configuration cfg = getConfiguration();
            Auth auth = getAuth();
            BucketManager bucketManager = new BucketManager(auth, cfg);
            
            String prefix = directory == null ? "" : directory;
            int limit = 1000;
            String delimiter = "";
            
            BucketManager.FileListIterator fileListIterator = 
                bucketManager.createFileListIterator(qiniuProperties.getBucketName(), prefix, limit, delimiter);
            
            while (fileListIterator.hasNext()) {
                FileInfo[] items = fileListIterator.next();
                for (FileInfo item : items) {
                    // 过滤掉目录，只返回文件
                    if (!item.key.endsWith("/")) {
                        result.add(item);
                    }
                }
            }
            
            log.info("获取文件列表成功，共{}个文件", result.size());
            return result;
            
        } catch (Exception ex) {
            log.error("获取文件列表失败：", ex);
            throw new ApiException("获取文件列表失败：" + ex.getMessage());
        }
    }

    /**
     * 生成文件访问token（用于私有空间）
     * @param directory 文件目录
     * @param fileName 文件名
     * @param expireInSeconds 过期时间（秒）
     * @return 带token的访问URL
     */
    public String generateAccessToken(String directory, String fileName, long expireInSeconds) {
        log.info("开始生成文件访问token，目录：{}，文件名：{}，过期时间：{}秒", directory, fileName, expireInSeconds);
        
        try {
            // 确保目录以/结尾
            if (directory != null && !directory.isEmpty() && !directory.endsWith("/")) {
                directory = directory + "/";
            }
            
            String key = (directory == null ? "" : directory) + fileName;
            String encodedKey = URLEncoder.encode(key, "utf-8").replace("+", "%20");
            String publicUrl = String.format("%s/%s", qiniuProperties.getDomain(), encodedKey);
            
            Auth auth = getAuth();
            String finalUrl = auth.privateDownloadUrl(publicUrl, expireInSeconds);
            
            log.info("生成访问token成功，URL：{}", finalUrl);
            return finalUrl;
            
        } catch (Exception ex) {
            log.error("生成访问token失败：", ex);
            throw new ApiException("生成访问token失败：" + ex.getMessage());
        }
    }

    /**
     * 生成文件访问token（默认10分钟过期）
     * @param directory 文件目录
     * @param fileName 文件名
     * @return 带token的访问URL
     */
    public String generateAccessToken(String directory, String fileName) {
        return generateAccessToken(directory, fileName, 600); // 默认10分钟
    }
}